package com.jasonzqshen.ifm.project;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;

import com.jasonzqshen.ifm.PluginConfiguration;
import com.jasonzqshen.ifm.utils.SystemLog;

public class FileCreator {
    /**
     * Create file resource in certain project
     * 
     * @param project
     */
    public static IFile CreateFileInProject(final String fileName,
            final String filePath, final IWizardContainer container,
            final InputStream initialStream) {
        // System Log
        final String taskName = String.format(
                "Create File '%s'  under path '%s'", fileName, filePath);
        SystemLog.logInfo(taskName);

        IContainer pathContainer = null;
        try {
            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            IResource resource = root.findMember(filePath);
            if (!resource.exists() || !(resource instanceof IContainer)) {
                String msg = String.format("File Path '%s' does not exist.",
                        filePath);
                throwCoreException(msg);
            }
            pathContainer = (IContainer) resource;
        } catch (CoreException e) {
            SystemLog.logError(e.getMessage(), e);
            return null;
        }
        final IFile file = pathContainer.getFile(new Path(fileName));

        // create the new project operation
        IRunnableWithProgress op = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor)
                    throws InvocationTargetException {
                try {
                    // create new file
                    monitor.beginTask(taskName, 1);

                    if (file.exists()) {
                        file.setContents(initialStream, true, true, monitor);
                    } else {
                        file.create(initialStream, true, monitor);
                    }
                    monitor.worked(1);

                } catch (CoreException e) {
                    SystemLog.logError(e.getMessage(), e);
                    throw new InvocationTargetException(e);
                } finally {
                    monitor.done();
                }
            }
        };

        // run operation
        try {
            container.run(true, true, op);
        } catch (InvocationTargetException e) {
            SystemLog.logError(e.getMessage(), e);
        } catch (InterruptedException e) {
            SystemLog.logError(e.getMessage(), e);
        }

        SystemLog
                .logInfo(String.format("File '%s' create complete.", fileName));
        return file;
    }

    /**
     * Open File For Editing
     * 
     * @param file
     */
    public static void openFile(final IFile file, IWizardContainer container,
            final Shell shell) {
        final String taskName = String.format(
                "Opening file '%s' for editing...", file.getName());
        SystemLog.logInfo(taskName);
        IRunnableWithProgress op = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor)
                    throws InvocationTargetException {
                monitor.beginTask(taskName, 1);

                Runnable runnable = new Runnable() {
                    public void run() {
                        IWorkbench workbench = PlatformUI.getWorkbench();
                        IWorkbenchWindow window = workbench
                                .getActiveWorkbenchWindow();

                        org.eclipse.ui.IWorkbenchPage page = window
                                .getActivePage();
                        try {
                            IDE.openEditor(page, file, true);
                        } catch (PartInitException _ex) {
                            SystemLog.logError(_ex.getMessage(), _ex);
                        }

                    }
                };

                // run open file
                shell.getDisplay().asyncExec(runnable);
            }
        };

        // run operation
        try {
            container.run(true, true, op);
        } catch (InvocationTargetException e) {
            SystemLog.logError(e.getMessage(), e);
        } catch (InterruptedException e) {
            SystemLog.logError(e.getMessage(), e);
        }
    }

    /**
     * Create Project File and open for editing
     * 
     * @param project
     */
    public static void CreateProjectFile(final IProject project,
            final IWizardContainer container, final Shell shell) {
        String projectName = project.getName();
        String projectFileName = String.format("%s.%s", projectName,
                PluginConfiguration.PROJECT_FILE_EXTENSION);
        String filePath = project.getFullPath().toString();
        InputStream initialStream = new ByteArrayInputStream(
                "Project File.".getBytes());

        IFile file = CreateFileInProject(projectFileName, filePath, container,
                initialStream);

        if (file == null) {
            return;
        }
        openFile(file, container, shell);
    }

    /**
     * create feature model file
     * 
     * @param filePath
     * @param fileName
     * @param container
     * @param shell
     */
    public static void createFeatureModelFile(final String filePath,
            final String fileName, final IWizardContainer container,
            final Shell shell) {
        InputStream featureModelInitStream = initializeFeatureModel();
        IFile file = CreateFileInProject(fileName, filePath, container,
                featureModelInitStream);
        openFile(file, container, shell);
    }

    /**
     * Initialize feature model
     * 
     * @return
     */
    public static InputStream initializeFeatureModel() {
        return new ByteArrayInputStream("Hello, World".getBytes());
    }

    /**
     * throw core exception
     * 
     * @param message
     * @throws CoreException
     */
    private static void throwCoreException(String message) throws CoreException {
        IStatus status = new Status(4, "Ifm", 0, message, null);
        throw new CoreException(status);
    }

}
